﻿using log4net;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using zkemkeeper;

namespace ZKDevice
{
    public class ZKDeviceAPIImpl : ZKDeviceAPI
    {
        private ILog log = LogManager.GetLogger(typeof(ZKDeviceAPIImpl));
        private ReaderWriterLockSlim writeLock = new ReaderWriterLockSlim();
        private CZKEMClass zkem = new CZKEMClass();
        private Int32 code = 0;
        private Timer timer;
        private int port;
        private string ip;

        public ZKDeviceAPIImpl()
        {
            zkem.OnDisConnected += Zkem_OnDisConnected;
            zkem.OnConnected += Zkem_OnConnected;
            timer = new Timer(CheckConnect, null, 10000, 60000);
        }

        private void CheckConnect(object state)
        {
            try
            {
                writeLock.EnterWriteLock();
                Int32 status = -1;
                zkem.GetConnectStatus(ref status);
                code = status;
                if (status == -1)
                {
                    log.InfoFormat("正在重新连接{0}:{1}", ip, port);
                    zkem.Connect_Net(ip, port);
                }
            }
            catch(Exception ex)
            {
                log.InfoFormat("");
            }
            finally
            {
                writeLock.ExitWriteLock();
            }

        }

        private void Zkem_OnConnected()
        {
            log.InfoFormat("己连接:{0}:{1}", ip,port);
        }


        private void Zkem_OnDisConnected()
        {
            log.InfoFormat("己断开:{0}:{1}", ip,port);
        }

        public bool IsConnected()
        {
            return code != -1;
        }

        public bool Connect(string ip,int port)
        {
            try
            {
                writeLock.EnterWriteLock();
                this.ip = ip;
                this.port = port;
                return zkem.Connect_Net(ip, port);
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }

        public void DisConnect()
        {
            timer.Dispose();
            zkem.Disconnect();
        }

        public bool DownloadUserInfo(UserInfo userInfo)
        {
            try
            {
                writeLock.EnterWriteLock();
                log.InfoFormat("开始下载权限：用户姓名【{0} - {1}】设备{2}",userInfo.identifier, userInfo.name, ip);
                if (userInfo.cardId == null || userInfo.cardId.Trim() == "")
                {
                    userInfo.cardId = userInfo.identifier + "";
                }
                bool result = zkem.SetStrCardNumber(userInfo.cardId);
                if (!result)
                {
                    return false;
                }
                result = zkem.SetUserInfo(1, userInfo.identifier, userInfo.name, "", 0, true);
                log.InfoFormat("下载用户【{0} - {1}】基本信息{2}", userInfo.identifier, userInfo.name, result ? "成功" : "失败");
                if (result)
                {
                    if (userInfo.fingerList != null && userInfo.fingerList.Count > 0)
                    {
                        for (int i = 0; i < userInfo.fingerList.Count && result; i++)
                        {
                            byte[] finger = userInfo.fingerList[i];
                            if (finger == null) continue;
                            bool setUserTmpStr = zkem.SetUserTmpExStr(1, Convert.ToString(userInfo.identifier), i, 1, Encoding.GetEncoding("GBK").GetString(finger));
                            result = result & setUserTmpStr;
                            log.InfoFormat("下载用户【{0}】第{1}枚指纹{2}", userInfo.name, i, result ? "成功" : "失败");
                        }
                    }
                    if (result && userInfo.face != null)
                    {
                        bool setUserFaceStr = zkem.SetUserFaceStr(1, Convert.ToString(userInfo.identifier), 0, Convert.ToBase64String(userInfo.face), userInfo.face.Length);
                        result = result & setUserFaceStr;
                        log.InfoFormat("下载用户【{0}】人脸{1}", userInfo.name, result ? "成功" : "失败");
                    }
                }
                return result;
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }

        public List<AttendanceLog> ReadAttendanceLog()
        {
            try
            {
                writeLock.EnterWriteLock();
                List<AttendanceLog> list = new List<AttendanceLog>();
                bool result = zkem.ReadGeneralLogData(1);
                if (result)
                {
                    int userid = 0;
                    int dwVerifyMode = 0;
                    int dwInOutMode = 0;
                    int dwYear = 0;
                    int dwMonth = 0;
                    int dwDay = 0;
                    int dwHour = 0;
                    int dwMinute = 0;
                    int dwSecond = 0;
                    int dwWorkCode = 0;
                    int dwReserved = 0;
                    bool getData = false;
                    while (getData = zkem.GetGeneralExtLogData(1, ref userid, ref dwVerifyMode, ref dwInOutMode, ref dwYear, ref dwMonth
                        , ref dwDay, ref dwHour, ref dwMinute, ref dwSecond, ref dwWorkCode, ref dwReserved))
                    {
                        DateTime d = new DateTime(dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond);
                        AttendanceLog log = new AttendanceLog();
                        log.identifier = userid + "";
                        log.logTime = d;
                        list.Add(log);
                    }
                }
                zkem.ClearGLog(1);
                return list;
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }

        public bool ValidUserInfo(int identifier, int fingerSize)
        {
            try
            {
                writeLock.EnterWriteLock();
                bool result = false;
                string name = "";
                string password = "";
                int privilege = 0;
                bool enabled = false;

                result = zkem.GetUserInfo(1, identifier, ref name, ref password, ref privilege, ref enabled);
                Console.WriteLine(result + "==" + name);
                int errorCode = 0;
                zkem.GetLastError(ref errorCode);
                if (!result)
                {
                    return false;
                }

                if (fingerSize > 0)
                {
                    string TmpData = "";
                    int TmpLength = 0;
                    int flag = 0;
                    int f = 0;
                    for (int i = 0; i < 15; i++)
                    {
                        if (zkem.GetUserTmpExStr(1, Convert.ToString(identifier), i, out flag, out TmpData, out TmpLength))
                        {
                            f++;
                        }
                    }
                    if (f < fingerSize)
                    {
                        return false;
                    }
                }

                return result;
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }

        public bool DeleteUserInfo(int identifier)
        {
            try
            {
                writeLock.EnterWriteLock();
                return zkem.DeleteEnrollData(1, identifier, 1, 12);
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }

        public bool ExistUserInfo(int identifier)
        {
            try
            {
                writeLock.EnterWriteLock();
                bool result = false;
                string name = "";
                string password = "";
                int privilege = 0;
                bool enabled = false;

                result = zkem.GetUserInfo(1, identifier, ref name, ref password, ref privilege, ref enabled);
                return result;
            }
            finally
            {
                writeLock.ExitWriteLock();
            }
        }
    }
}
